﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YJKRGeometry.CurveUtility;

namespace HYCoordinate
{
	public static class Utiltiy
	{
		public static string GetAppRootPath()
		{
			string location = Assembly.GetExecutingAssembly().Location;
			int length = location.LastIndexOf("\\");
			string text = location.Substring(0, length);
			length = text.LastIndexOf("\\");
			return text.Substring(0, length);
		}

		internal static List<Parameter> GetParametersByName(this Element input, string inputName)
		{
			List<Parameter> list = new List<Parameter>();
			foreach (object obj in input.Parameters)
			{
				Parameter parameter = (Parameter)obj;
				if (parameter.Definition.Name.Equals(inputName))
				{
					list.Add(parameter);
				}
			}
			return list;
		}

		internal static Curve CreateSameOffset(this Curve input, double offsetDist, XYZ normal)
		{
			Curve result;
			try
			{
				result = (input.GetType().InvokeMember(StaticRescource.Str_CreateOffest, BindingFlags.InvokeMethod, null, input, new object[]
				{
					offsetDist,
					normal
				}) as Curve);
			}
			catch (Exception)
			{
				if (normal.Z > 0.0)
				{
					result = CurveUtility.CreateOffsetCurve(input, offsetDist);
				}
				else
				{
					result = CurveUtility.CreateOffsetCurve(input, -offsetDist);
				}
			}
			return result;
		}

		internal static Curve CreateReversedUtility(this Curve input)
		{
			Curve result;
			try
			{
				result = (input.GetType().InvokeMember(StaticRescource.Str_CreateReversed, BindingFlags.InvokeMethod, null, input, new object[0]) as Curve);
			}
			catch (Exception ex)
			{
				if (input is Line)
				{
					result = Line.CreateBound(input.GetEndPoint(1), input.GetEndPoint(0));
				}
				else
				{
					if (!(input is Arc))
					{
						throw ex;
					}
					XYZ center = (input as Arc).Center;
					result = Arc.Create(input.GetEndPoint(1), input.GetEndPoint(0), center);
				}
			}
			return result;
		}

		public static double FeetMMChange(double input, bool ifFeetToMM = false)
		{
			if (ifFeetToMM)
			{
				return input * 304.8;
			}
			return input / 304.8;
		}

		internal static Line GetMidAixZPlane(BoundingBoxXYZ input)
		{
			XYZ midPoint = Utiltiy.GetMidPoint(input.Max, input.Min);
			return Line.CreateBound(midPoint, new XYZ(midPoint.X, midPoint.Y, midPoint.Z + 1.0));
		}

		internal static XYZ GetLineMidPoint(Line input)
		{
			return Utiltiy.GetMidPoint(input.GetEndPoint(0), input.GetEndPoint(1));
		}

		internal static XYZ GetBaseXVector(XYZ input)
		{
			if (input == null)
			{
				return null;
			}
			return new XYZ(1.0, 0.0, input.Z);
		}

		internal static ElementId GetWantedElementId(Document m_doc, string[] elementNames)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(m_doc);
			ElementClassFilter elementClassFilter = new ElementClassFilter(typeof(TextNoteType));
			foreach (Element element in filteredElementCollector.WherePasses(elementClassFilter).ToElements())
			{
				foreach (string pattern in elementNames)
				{
					if (Regex.IsMatch(element.Name, pattern))
					{
						return element.Id;
					}
				}
			}
			return null;
		}

		internal static XYZ GetAVectorAnotherXY(XYZ input)
		{
			return new XYZ(-input.X, -input.Y, input.Z);
		}

		internal static bool CheckNoneEndInterintersection(List<Curve> input)
		{
			for (int i = 0; i < input.Count; i++)
			{
				for (int j = i + 1; j < input.Count; j++)
				{
					if (Utiltiy.ifIsNoneEndIntersection(input[i], input[j]))
					{
						return true;
					}
				}
			}
			return false;
		}

		private static bool ifIsNoneEndIntersection(Curve inputOne, Curve inputTwo)
		{
			IntersectionResultArray intersectionResultArray;
			SetComparisonResult setComparisonResult = inputOne.Intersect(inputTwo, out intersectionResultArray);
			bool flag = false;
			bool flag2 = false;
			if (8 != (int)setComparisonResult)
			{
				return false;
			}
			XYZ xyzpoint = intersectionResultArray.get_Item(0).XYZPoint;
			for (int i = 0; i < 2; i++)
			{
				if (xyzpoint.IsAlmostEqualTo(inputOne.GetEndPoint(i)))
				{
					flag = true;
				}
				if (xyzpoint.IsAlmostEqualTo(inputTwo.GetEndPoint(i)))
				{
					flag2 = true;
				}
			}
			return !flag || !flag2;
		}

		internal static XYZ GetPointOnArcByTwoArcOneArc(XYZ pointOne, XYZ pointTwo, double radius, XYZ driectionCutLineOne = null, XYZ driectionCutLineTwo = null, XYZ inputCentre = null)
		{
			if (driectionCutLineOne == null && driectionCutLineTwo == null)
			{
				throw new CornerMakerException(StaticRescource.StrError_NullValue);
			}
			XYZ xyz = null;
			XYZ midPoint = Utiltiy.GetMidPoint(pointOne, pointTwo);
			if (inputCentre == null)
			{
				if (driectionCutLineOne != null)
				{
					XYZ xyz2 = new XYZ(-driectionCutLineOne.Y, driectionCutLineOne.X, driectionCutLineOne.Z).Normalize();
					if (pointOne.Add(xyz2.Multiply(radius)).DistanceTo(midPoint) > pointOne.Add(Utiltiy.GetAVectorAnotherXY(xyz2).Multiply(radius)).DistanceTo(midPoint))
					{
						xyz2 = Utiltiy.GetAVectorAnotherXY(xyz2).Normalize();
					}
					xyz = pointOne.Add(xyz2.Multiply(radius));
				}
				else if (driectionCutLineTwo != null)
				{
					XYZ xyz2 = new XYZ(-driectionCutLineTwo.Y, driectionCutLineTwo.X, driectionCutLineTwo.Z).Normalize();
					if (pointTwo.Add(xyz2.Multiply(radius)).DistanceTo(midPoint) > pointTwo.Add(Utiltiy.GetAVectorAnotherXY(xyz2).Multiply(radius)).DistanceTo(midPoint))
					{
						xyz2 = Utiltiy.GetAVectorAnotherXY(xyz2).Normalize();
					}
					xyz = pointTwo.Add(xyz2.Multiply(radius));
				}
			}
			else
			{
				xyz = inputCentre;
			}
			if (xyz.IsAlmostEqualTo(midPoint))
			{
				throw new CornerMakerException(StaticRescource.StrError_PointsNear);
			}
			XYZ xyz3 = midPoint.Add(-xyz).Normalize();
			return xyz.Add(xyz3.Multiply(radius));
		}

		public static XYZ GetMidPoint(XYZ pointOne, XYZ pointTwo)
		{
			if (pointOne.IsAlmostEqualTo(pointTwo))
			{
				throw new CornerMakerException(StaticRescource.StrError_PointsNear);
			}
			return pointOne.Add(pointTwo).Divide(2.0);
		}

		private static XYZ GetInnerIntersectionPointDifWitdh(TwoInputDataPakcer inputDataOne, TwoInputDataPakcer inputDataTwo, out List<Curve> linesOne, out List<Curve> linesTwo)
		{
			List<Curve> list = new List<Curve>();
			List<Curve> list2 = new List<Curve>();
			XYZ xyz = null;
			linesOne = new List<Curve>();
			linesTwo = new List<Curve>();
			int num = -1;
			int num2 = -1;
			XYZ midPoint = Utiltiy.GetMidPoint(inputDataOne.GetPoint(0), inputDataTwo.GetPoint(1));
			double num3 = Math.Max(inputDataOne.GetParameters(1)[UseParameterEnum.Width], inputDataTwo.GetParameters(1)[UseParameterEnum.Width]);
			list.Add(inputDataOne.GetLine(3).CreateSameOffset(num3 / 2.0, StaticRescource.GetXYPlaneNorme(0)));
			list.Add(inputDataOne.GetLine(3).CreateSameOffset(num3 / 2.0, StaticRescource.GetXYPlaneNorme(1)));
			list2.Add(inputDataTwo.GetLine(3).CreateSameOffset(num3 / 2.0, StaticRescource.GetXYPlaneNorme(0)));
			list2.Add(inputDataTwo.GetLine(3).CreateSameOffset(num3 / 2.0, StaticRescource.GetXYPlaneNorme(1)));
			IntersectionResultArray intersectionResultArray;
			for (int i = 0; i <= 1; i++)
			{
				for (int j = 0; j <= 1; j++)
				{
					SetComparisonResult setComparisonResult = list[i].Intersect(list2[j], out intersectionResultArray);
					if (8 == (int)setComparisonResult)
					{
						if (xyz == null)
						{
							xyz = intersectionResultArray.get_Item(0).XYZPoint;
							linesOne.Add(inputDataOne.GetLine(i));
							linesTwo.Add(inputDataTwo.GetLine(j));
							num = i;
							num2 = j;
						}
						else if (xyz.DistanceTo(midPoint) > intersectionResultArray.get_Item(0).XYZPoint.DistanceTo(midPoint))
						{
							xyz = intersectionResultArray.get_Item(0).XYZPoint;
							linesOne[0] = inputDataOne.GetLine(i);
							linesTwo[0] = inputDataTwo.GetLine(j);
							num = i;
							num2 = j;
						}
					}
				}
			}
			if (xyz == null)
			{
				if (Utiltiy.m_doc != null)
				{
					Transaction transaction = new Transaction(Utiltiy.m_doc, "test");
					List<XYZ> list3 = new List<XYZ>();
					transaction.Start();
					if (Utiltiy.m_doc != null)
					{
						for (int k = 0; k <= 3; k++)
						{
							Utiltiy.m_doc.Create.NewDetailCurve(Utiltiy.m_doc.ActiveView, inputDataOne.GetLine(k));
							Utiltiy.m_doc.Create.NewDetailCurve(Utiltiy.m_doc.ActiveView, inputDataTwo.GetLine(k));
							list3.Add(inputDataOne.GetLine(k).GetEndPoint(0));
							list3.Add(inputDataOne.GetLine(k).GetEndPoint(1));
							list3.Add(inputDataTwo.GetLine(k).GetEndPoint(1));
							list3.Add(inputDataTwo.GetLine(k).GetEndPoint(0));
						}
					}
					transaction.Commit();
					double z = list3[0].Z;
					foreach (XYZ xyz2 in list3)
					{
						if (xyz2.Z != z)
						{
							TaskDialog.Show("异常日志-Z值不同", xyz2.Z.ToString() + "   " + z.ToString());
						}
					}
				}
				throw new CornerMakerException(StaticRescource.StrNonIntersection);
			}
			if (1 != linesOne.Count && 1 != linesTwo.Count)
			{
				throw new CornerMakerException(StaticRescource.StrErrorIntersection);
			}
			if (num == 0)
			{
				linesOne.Add(inputDataOne.GetLine(1));
			}
			else
			{
				linesOne.Add(inputDataOne.GetLine(0));
			}
			if (num2 == 0)
			{
				linesTwo.Add(inputDataTwo.GetLine(1));
			}
			else
			{
				linesTwo.Add(inputDataTwo.GetLine(0));
			}
			Line line = Line.CreateBound(linesOne[0].GetEndPoint(0), linesOne[0].GetEndPoint(1));
			Curve curve = Line.CreateBound(linesTwo[0].GetEndPoint(0), linesTwo[0].GetEndPoint(1));
			line.MakeUnbound();
			curve.MakeUnbound();
			intersectionResultArray = null;
			line.Intersect(curve, out intersectionResultArray);
			if (intersectionResultArray != null)
			{
				return intersectionResultArray.get_Item(0).XYZPoint;
			}
			return null;
		}

		internal static XYZ GetInnerIntersectionPoint(TwoInputDataPakcer inputDataOne, TwoInputDataPakcer inputDataTwo, out List<Curve> linesOne, out List<Curve> linesTwo)
		{
			if (inputDataOne.GetParameters(1)[UseParameterEnum.Width] != inputDataTwo.GetParameters(1)[UseParameterEnum.Width])
			{
				XYZ innerIntersectionPointDifWitdh = Utiltiy.GetInnerIntersectionPointDifWitdh(inputDataOne, inputDataTwo, out linesOne, out linesTwo);
				if (innerIntersectionPointDifWitdh == null)
				{
					throw new CornerMakerException(StaticRescource.StrNonIntersection);
				}
				return innerIntersectionPointDifWitdh;
			}
			else
			{
				XYZ xyz = null;
				linesOne = new List<Curve>();
				linesTwo = new List<Curve>();
				int num = -1;
				int num2 = -1;
				XYZ midPoint = Utiltiy.GetMidPoint(inputDataOne.GetPoint(0), inputDataTwo.GetPoint(1));
				for (int i = 0; i <= 1; i++)
				{
					for (int j = 0; j <= 1; j++)
					{
						IntersectionResultArray intersectionResultArray;
						SetComparisonResult setComparisonResult = inputDataOne.GetLine(i).Intersect(inputDataTwo.GetLine(j), out intersectionResultArray);
						if (8 == (int)setComparisonResult)
						{
							if (xyz == null)
							{
								xyz = intersectionResultArray.get_Item(0).XYZPoint;
								linesOne.Add(inputDataOne.GetLine(i));
								linesTwo.Add(inputDataTwo.GetLine(j));
								num = i;
								num2 = j;
							}
							else if (xyz.DistanceTo(midPoint) > intersectionResultArray.get_Item(0).XYZPoint.DistanceTo(midPoint))
							{
								xyz = intersectionResultArray.get_Item(0).XYZPoint;
								linesOne[0] = inputDataOne.GetLine(i);
								linesTwo[0] = inputDataTwo.GetLine(j);
								num = i;
								num2 = j;
							}
						}
					}
				}
				if (xyz == null)
				{
					if (Utiltiy.m_doc != null)
					{
						Transaction transaction = new Transaction(Utiltiy.m_doc, "test");
						List<XYZ> list = new List<XYZ>();
						transaction.Start();
						if (Utiltiy.m_doc != null)
						{
							for (int k = 0; k <= 3; k++)
							{
								Utiltiy.m_doc.Create.NewDetailCurve(Utiltiy.m_doc.ActiveView, inputDataOne.GetLine(k));
								Utiltiy.m_doc.Create.NewDetailCurve(Utiltiy.m_doc.ActiveView, inputDataTwo.GetLine(k));
								list.Add(inputDataOne.GetLine(k).GetEndPoint(0));
								list.Add(inputDataOne.GetLine(k).GetEndPoint(1));
								list.Add(inputDataTwo.GetLine(k).GetEndPoint(1));
								list.Add(inputDataTwo.GetLine(k).GetEndPoint(0));
							}
						}
						transaction.Commit();
						double z = list[0].Z;
						foreach (XYZ xyz2 in list)
						{
							if (xyz2.Z != z)
							{
								TaskDialog.Show("异常日志-Z值不同", xyz2.Z.ToString() + "   " + z.ToString());
							}
						}
					}
					throw new CornerMakerException(StaticRescource.StrNonIntersection);
				}
				if (1 != linesOne.Count && 1 != linesTwo.Count)
				{
					throw new CornerMakerException(StaticRescource.StrErrorIntersection);
				}
				if (num == 0)
				{
					linesOne.Add(inputDataOne.GetLine(1));
				}
				else
				{
					linesOne.Add(inputDataOne.GetLine(0));
				}
				if (num2 == 0)
				{
					linesTwo.Add(inputDataTwo.GetLine(1));
				}
				else
				{
					linesTwo.Add(inputDataTwo.GetLine(0));
				}
				return xyz;
			}
		}

		internal static XYZ GetIntersectionPointOnUnbound(Line lineOne, Line lineTwo)
		{
			Line line = Line.CreateBound(lineOne.GetEndPoint(0), lineOne.GetEndPoint(1));
			Line line2 = lineTwo.CreateReversedUtility() as Line;
			line.MakeUnbound();
			line2.MakeUnbound();
			IntersectionResultArray intersectionResultArray;
            if ((int)line.Intersect(line2, out intersectionResultArray) != 8)
			{
				throw new CornerMakerException(StaticRescource.StrNonIntersection);
			}
			return intersectionResultArray.get_Item(0).XYZPoint;
		}

		internal static List<Curve> GetLstBoundLineCurve(List<XYZ> inputPoints)
		{
			List<Curve> list = new List<Curve>();
			int i = 0;
			while (i < inputPoints.Count)
			{
				Line item;
				if (i != inputPoints.Count - 1)
				{
					if (!inputPoints[i].IsAlmostEqualTo(inputPoints[i + 1]))
					{
						item = Line.CreateBound(inputPoints[i], inputPoints[i + 1]);
						goto IL_6D;
					}
				}
				else if (!inputPoints[i].IsAlmostEqualTo(inputPoints[0]))
				{
					item = Line.CreateBound(inputPoints[i], inputPoints[0]);
					goto IL_6D;
				}
				IL_74:
				i++;
				continue;
				IL_6D:
				list.Add(item);
				goto IL_74;
			}
			return list;
		}

		public static List<Curve> GetNormalLineBoundryCurves(XYZ startPoint, XYZ endPoint, Dictionary<UseParameterEnum, double> inputParams)
		{
			List<Curve> list = new List<Curve>();
			Line input = Line.CreateBound(startPoint, endPoint);
			Line line = input.CreateSameOffset(inputParams[UseParameterEnum.Width] / 2.0, StaticRescource.GetXYPlaneNorme(0)) as Line;
			Line line2 = input.CreateSameOffset(inputParams[UseParameterEnum.Width] / 2.0, StaticRescource.GetXYPlaneNorme(1)) as Line;
			list.Add(Line.CreateBound(line2.GetEndPoint(0), line.GetEndPoint(0)));
			list.Add(line);
			list.Add(Line.CreateBound(line.GetEndPoint(1), line2.GetEndPoint(1)));
			list.Add(line2.CreateReversedUtility());
			return list;
		}

		internal static bool GetCornernRectangle(ThreeInputDataPacker input, out XYZ innerpoint, out XYZ outerPoint, out XYZ pointL, out XYZ pointR)
		{
			List<Curve> list;
			List<Curve> list2;
			XYZ innerIntersectionPoint = Utiltiy.GetInnerIntersectionPoint(input.GetTwoInputData(0), input.GetTwoInputData(1), out list, out list2);
			XYZ intersectionPointOnUnbound = Utiltiy.GetIntersectionPointOnUnbound(list[1] as Line, list2[1] as Line);
			innerpoint = innerIntersectionPoint;
			outerPoint = intersectionPointOnUnbound;
			pointL = null;
			pointR = null;
			if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] == input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
			{
				pointL = list[1].Project(innerIntersectionPoint).XYZPoint;
				pointR = list2[1].Project(innerIntersectionPoint).XYZPoint;
				return false;
			}
			if (input.GetTwoInputData(0).GetParameters(1)[UseParameterEnum.Width] > input.GetTwoInputData(1).GetParameters(1)[UseParameterEnum.Width])
			{
				switch (Utiltiy.pointLocationWithLine(intersectionPointOnUnbound, list[1] as Line, 0))
				{
				case PointLocationWithLineEnum.OnEndPoint:
					pointL = list[0].Project(intersectionPointOnUnbound).XYZPoint;
					pointR = list2[1].Project(innerIntersectionPoint).XYZPoint;
					return true;
				case PointLocationWithLineEnum.NoneSameLine:
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				case PointLocationWithLineEnum.OnLine:
					pointL = list[0].Project(intersectionPointOnUnbound).XYZPoint;
					pointR = list2[1].Project(innerIntersectionPoint).XYZPoint;
					return true;
				case PointLocationWithLineEnum.OnLineExtnend:
					pointL = list[1].Project(innerIntersectionPoint).XYZPoint;
					pointR = list2[1].Project(innerIntersectionPoint).XYZPoint;
					return false;
				default:
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				}
			}
			else
			{
				switch (Utiltiy.pointLocationWithLine(intersectionPointOnUnbound, list2[1] as Line, 1))
				{
				case PointLocationWithLineEnum.OnEndPoint:
					pointL = list[1].Project(innerIntersectionPoint).XYZPoint;
					pointR = list2[0].Project(intersectionPointOnUnbound).XYZPoint;
					return true;
				case PointLocationWithLineEnum.NoneSameLine:
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				case PointLocationWithLineEnum.OnLine:
					pointL = list[1].Project(innerIntersectionPoint).XYZPoint;
					pointR = list2[0].Project(intersectionPointOnUnbound).XYZPoint;
					return true;
				case PointLocationWithLineEnum.OnLineExtnend:
					pointL = list[1].Project(innerIntersectionPoint).XYZPoint;
					pointR = list2[1].Project(innerIntersectionPoint).XYZPoint;
					return false;
				default:
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				}
			}
		}

		private static PointLocationWithLineEnum pointLocationWithLine(XYZ inputPoint, Line inputLine, int errorSide = -1)
		{
			double num = 0.001;
			int i = 0;
			while (i <= 1)
			{
				if (inputPoint.IsAlmostEqualTo(inputLine.GetEndPoint(i)))
				{
					if (i == errorSide)
					{
						throw new CornerMakerException(StaticRescource.StrCornerOutSide);
					}
					return PointLocationWithLineEnum.OnEndPoint;
				}
				else
				{
					i++;
				}
			}
			XYZ xyz = inputLine.Direction.Normalize();
			XYZ xyz2 = Line.CreateBound(inputPoint, inputLine.GetEndPoint(0)).Direction.Normalize();
			if (!xyz2.IsAlmostEqualTo(xyz) && !xyz2.IsAlmostEqualTo(-xyz))
			{
				return PointLocationWithLineEnum.NoneSameLine;
			}
			if (Math.Abs(inputPoint.DistanceTo(inputLine.GetEndPoint(0)) + inputPoint.DistanceTo(inputLine.GetEndPoint(1)) - inputLine.Length) < num)
			{
				return PointLocationWithLineEnum.OnLine;
			}
			if (-1 != errorSide)
			{
				if (errorSide == 0 && inputPoint.DistanceTo(inputLine.GetEndPoint(errorSide)) < inputPoint.DistanceTo(inputLine.GetEndPoint(1)))
				{
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				}
				if (1 == errorSide && inputPoint.DistanceTo(inputLine.GetEndPoint(errorSide)) < inputPoint.DistanceTo(inputLine.GetEndPoint(0)))
				{
					throw new CornerMakerException(StaticRescource.StrCornerOutSide);
				}
			}
			return PointLocationWithLineEnum.OnLineExtnend;
		}

		internal static CurveArray GetACloseCurveArrayFormList(List<Curve> lstCloseCurves)
		{
			return null;
		}

		private static Curve GetALinkedCurve(Curve fromCurve, ref List<Curve> input, int pointIndex)
		{
			XYZ endPoint = fromCurve.GetEndPoint(pointIndex);
			int num = -1;
			int num2 = -1;
			int num3 = 0;
			if (pointIndex == 0)
			{
				num = 1;
			}
			else
			{
				num = 0;
			}
			foreach (Curve input2 in input)
			{
				if (-1 != Utiltiy.GetCurveLindkPointIndex(endPoint, input2))
				{
					num2 = num3;
					break;
				}
				num3++;
			}
			if (-1 == num2 || -1 == num)
			{
				return null;
			}
			Curve curve = input[num2];
			input.RemoveAt(num2);
			if (num == Utiltiy.GetCurveLindkPointIndex(endPoint, curve))
			{
				return curve;
			}
			return curve.CreateReversedUtility();
		}

		private static int GetCurveLindkPointIndex(XYZ from, Curve input)
		{
			for (int i = 0; i < 2; i++)
			{
				if (input.GetEndPoint(i).IsAlmostEqualTo(from))
				{
					return i;
				}
			}
			return -1;
		}

		internal static Document m_doc;
	}
}
